﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using io = System.IO;
using wf = System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Threading;
using System.Collections;
using System.ComponentModel;

namespace editor.app
{
    /// <summary>
    /// MainJSWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainJSWindow : Window
    {
        comm.objst.DMainJS _mainJS = null;
        Dictionary<string, IDictionary> _valueDic = null;
        string _fileName = "";
        string _sign1 = "", _sign2 = "";
        string _lastThId = "";
        wf.PropertyGrid _propGrid = new wf.PropertyGrid { PropertySort = wf.PropertySort.Categorized };

        public MainJSWindow()
        {
            InitializeComponent();
            this.LoadConfig1();

            //Content = new comm.editor.UCLinearTree(null, true); return;

            winhost1.Child = _propGrid;
            _propGrid.PropertyValueChanged += new wf.PropertyValueChangedEventHandler((o, e) =>
            {
                FillJson();
            });

            _fileName = io.Path.Combine(App.DefineFile.Folder, comm.objst.DMainJS.FILE_NAME);
            OpenFile();

            KeyDown += new KeyEventHandler(MainJSWindow_KeyDown);
            btnNew.Click += new RoutedEventHandler(btnNew_Click);
            btnReload.Click += new RoutedEventHandler(btnReload_Click);
            btnEdit.Click += new RoutedEventHandler(btnEdit_Click);
            treeView.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(treeView_SelectedItemChanged);
            tbJson.TextChanged += new TextChangedEventHandler(tbJson_TextChanged);
            tbSearch.TextChanged += new TextChangedEventHandler(tbSearch_TextChanged);
            btnBack.Click += new RoutedEventHandler(btnBack_Click);
            btnNewPlan.Click += new RoutedEventHandler(btnNewPlan_Click);

            #region loop
            comm.ThreadHelper.Run(() =>
            {
                while (true)
                {
                    if (_mainJS != null)
                    {
                        var isChange = CheckSignChange();
                        Dispatcher.Invoke(new Action(() =>
                        {
                            Title = io.Path.GetFileName(_fileName) + (isChange ? "*" : "");

                            if (!tbJson.IsFocused)
                            {
                                FillJson();
                            }
                        }));
                    }
                    Thread.Sleep(100);
                }
            });
            #endregion
        }

        void btnNewPlan_Click(object sender, RoutedEventArgs e)
        {
            var obj = GetSelObj();
            var planDic = ((comm.objst.IExistPlan)obj).GetPlanDic();
            var newPlan = comm.BinarySerializer.Deserialize(comm.BinarySerializer.Serialize(planDic[comm.objst.DPlan.DEFAULT_KEY]));
            planDic.Add(comm.GUID.NewString(), newPlan);
            FillPlan();
        }
        void btnBack_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                _lastTb.Background = null;
            }
            catch (Exception)
            {
            }
            FillPropEdit();
        }
        void tbSearch_TextChanged(object sender, TextChangedEventArgs e)
        {
            comm.ThreadHelper.Stop(_lastThId);
            _lastThId = comm.ThreadHelper.Run(() =>
            {
                Thread.Sleep(200);
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    _mainJS.DesignSearchKey = tbSearch.Text;
                    Fill();
                }));
            });
        }
        void tbJson_TextChanged(object sender, TextChangedEventArgs e)
        {
            var keys = GetSelKey();
            var obj = GetSelObj();
            if (obj != null && tbJson.IsFocused)
            {
                try
                {
                    _valueDic[keys[0]][keys[1]] = comm.JsonSerializer.Deserialize(obj.GetType(), tbJson.Text);
                    tbJson.Opacity = 1;
                    FillPropEdit();
                }
                catch (Exception)
                {
                    tbJson.Opacity = .6;
                }
            }
        }
        void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (treeView.SelectedItem != null)
            {
                var tvi = (TreeViewItem)treeView.SelectedItem;
                if (GetSelKey() != null)
                {
                    _mainJS.DesignSelKey = tvi.Tag.ToString();
                }
            }
            FillPlan();
            FillPropEdit();
            FillJson();
            FillEVPropEdit();
        }
        void btnEdit_Click(object sender, RoutedEventArgs e)
        {
            var window = new TextWindow
            {
                Width = 900,
                Height = 600,
                InputText = comm.JsonSerializer.Serialize(_mainJS, false, true)
            };
            window.ShowDialog();
            try
            {
                var mainJS = comm.JsonSerializer.Deserialize<comm.objst.DMainJS>(window.InputText);
                if (mainJS != null)
                {
                    _mainJS = mainJS;
                    Fill();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        void MainJSWindow_KeyDown(object sender, KeyEventArgs e)
        {
            if (Keyboard.Modifiers == ModifierKeys.Control)
            {
                if (e.Key == Key.S)
                {
                    SaveFile();
                }
            }
        }
        void btnReload_Click(object sender, RoutedEventArgs e)
        {
            if (_fileName != null)
            {
                OpenFile();
            }
        }
        void btnNew_Click(object sender, RoutedEventArgs e)
        {
            var sfd = new wf.SaveFileDialog { FileName = comm.objst.DMainJS.FILE_NAME };
            if (sfd.ShowDialog().ToString() == "OK")
            {
                _mainJS = new comm.objst.DMainJS();
                _fileName = sfd.FileName;
                SaveFile();
                OpenFile();
            }
        }
        void mDel_Click(object sender, RoutedEventArgs e)
        {
            var keys = GetSelKey();
            if (keys != null)
            {
                var idic = _valueDic[keys[0]];
                idic.Remove(keys[1]);
                Fill();
            }
        }
        void mCopy_Click(object sender, RoutedEventArgs e)
        {
            var keys = GetSelKey();
            if (keys != null)
            {
                var idic = _valueDic[keys[0]];
                var obj = GetSelObj();
                var newObj = comm.BinarySerializer.Deserialize(comm.BinarySerializer.Serialize(obj));
                var ix = 0;
                while (true)
                {
                    ix++;
                    var key2 = keys[1].ToString() + ix;
                    if (!idic.Contains(key2))
                    {
                        idic.Add(key2, newObj);
                        break;
                    }
                }
                Fill();
            }
        }

        TextBox _lastTb = null;

        string[] GetSelKey()
        {
            if (treeView.SelectedItem != null)
            {
                var tvi = (TreeViewItem)treeView.SelectedItem;
                var key = tvi.Tag.ToString();
                var ss = key.Split(',');
                if (ss.Length == 2)
                {
                    return ss;
                }
            }
            return null;
        }
        object GetSelObj()
        {
            var keys = GetSelKey();
            if (keys != null)
            {
                return _valueDic[keys[0]][keys[1]];
            }
            return null;
        }

        void FillPlan()
        {
            var obj = GetSelObj();
            if (obj is comm.objst.IExistPlan)
            {
                spPlan.Children.Clear();
                var planDic = ((comm.objst.IExistPlan)obj).GetPlanDic();
                foreach (var key in planDic.Keys)
                {
                    var key2 = key;
                    var plan = (comm.objst.DPlan)planDic[key];
                    var grid = new Grid { Margin = new Thickness(0, 0, 0, 4) };

                    #region tb
                    var tbName = new TextBox
                    {
                        Tag = key,
                        Text = key.ToString(),
                        BorderThickness = new Thickness(0),
                        Margin = new Thickness(0, 0, 24, 0)
                    };
                    tbName.GotFocus += new RoutedEventHandler((o, e) =>
                    {
                        try
                        {
                            _lastTb.Background = null;
                        }
                        catch (Exception)
                        {
                        }
                        _lastTb = tbName;
                        _propGrid.SelectedObject = plan;
                        _lastTb.Background = new SolidColorBrush(Color2.Green(20));
                    });
                    tbName.TextChanged += new TextChangedEventHandler((o, e) =>
                    {
                        var key3 = tbName.Tag.ToString();
                        var newKey = tbName.Text.Trim();
                        if (key3 == newKey)
                        {
                            return;
                        }
                        if (key3 != comm.objst.DPlan.DEFAULT_KEY && !planDic.Contains(newKey))
                        {
                            var obj2 = planDic[key3];
                            planDic.Remove(key3);
                            planDic.Add(newKey, obj2);
                            tbName.Tag = newKey;
                        }
                        else
                        {
                            tbName.Text = key3;
                        }
                    });
                    grid.Children.Add(tbName);
                    #endregion

                    #region btnDel
                    var btnDel = new Button
                    {
                        Content = "X",
                        Width = 22,
                        Height = 22,
                        VerticalAlignment = VerticalAlignment.Center,
                        HorizontalAlignment = HorizontalAlignment.Right
                    };
                    btnDel.Click += new RoutedEventHandler((o, e) =>
                    {
                        planDic.Remove(key2);
                        FillPlan();
                        FillPropEdit();
                    });
                    grid.Children.Add(btnDel);
                    #endregion

                    if (key.ToString() == comm.objst.DPlan.DEFAULT_KEY)
                    {
                        tbName.IsReadOnly = true;
                        btnDel.IsEnabled = false;
                    }

                    spPlan.Children.Add(grid);
                }
                svPlan.Visibility = Visibility.Visible;
                gridEdit.Margin = new Thickness(400, 0, 0, 0);
            }
            else
            {
                svPlan.Visibility = Visibility.Collapsed;
                gridEdit.Margin = new Thickness(220, 0, 0, 0);
            }
        }
        void FillJson()
        {
            var obj = GetSelObj();
            if (obj != null)
            {
                tbJson.Text = comm.JsonSerializer.Serialize(obj, false);
            }
        }
        void FillPropEdit()
        {
            var obj = GetSelObj();
            if (obj != null)
            {
                _propGrid.SelectedObject = obj;
            }
        }
        void FillEVPropEdit()
        {
            //tabEV.Items.Clear();
            //var obj = GetSelObj();
            //var keys = GetSelKey();
            //if (obj is comm.objst.IClassBind)
            //{
            //    var evDic = _mainJS.AllObjEVDic[keys[0] + "," + keys[1]].EVDic;
            //    foreach (var evKey in evDic.Keys)
            //    {
            //        tabEV.Items.Add(new TabItem
            //        {
            //            Header = evKey,
            //            Content = new WindowsFormsHost
            //            {
            //                Child = new wf.PropertyGrid
            //                {
            //                    SelectedObject = evDic[evKey].Value
            //                }
            //            }
            //        });
            //    }
            //    if (tabEV.Items.Count > 0)
            //    {
            //        tabEV.SelectedIndex = 0;
            //    }
            //}
        }
        void Fill()
        {
            tbSearch.Text = _mainJS.DesignSearchKey;

            if (treeView.SelectedItem != null)
            {
                var tvi = (TreeViewItem)treeView.SelectedItem;
                _mainJS.DesignSelKey = tvi.Tag.ToString();
            }
            treeView.Items.Clear();

            var stxt = tbSearch.Text.Trim().ToLower();
            var tviDic = new Dictionary<string, TreeViewItem>();
            foreach (var key in _valueDic.Keys)
            {
                var key2 = key;
                var dic = _valueDic[key];

                #region type
                if (!tviDic.ContainsKey(key))
                {
                    var tvi = new TreeViewItem { Tag = key };
                    tvi.PreviewMouseUp += new MouseButtonEventHandler((o, e) =>
                    {
                        _mainJS.DesignTreeItemExpandDic[key2] = tvi.IsExpanded;
                    });

                    if (_mainJS.DesignTreeItemExpandDic.ContainsKey(key))
                    {
                        tvi.IsExpanded = _mainJS.DesignTreeItemExpandDic[key];
                    }
                    else if (key != comm.DefineFile.TYPE_NVALUE && key != comm.DefineFile.TYPE_LANGUAGE)
                    {
                        tvi.IsExpanded = true;
                    }

                    if (_mainJS.DesignSelKey == key)
                    {
                        tvi.IsSelected = true;
                    }

                    #region contextMenu
                    var contextMenu = new ContextMenu { FontSize = 14 };
                    contextMenu.Opened += new RoutedEventHandler((o, e) =>
                    {
                        tvi.IsSelected = true;
                    });
                    TextOptions.SetTextFormattingMode(contextMenu, TextFormattingMode.Display);

                    if (key == comm.DefineFile.TYPE_ITEM_CATEGORY)
                    {
                        #region TYPE_ITEM_CATEGORY
                        var mEditAll = new MenuItem { Header = "Edit All" };
                        mEditAll.Click += new RoutedEventHandler((o, e) =>
                        {
                            var nodeDic = new Dictionary<string, comm.objst.ILinearTreeNode>();
                            foreach (var cateKey in dic.Keys)
                            {
                                nodeDic.Add(cateKey.ToString(), (comm.objst.ILinearTreeNode)dic[cateKey]);
                            }
                            var uc = new comm.editor.UCLinearTree(nodeDic, true);
                            var window = new Window { Width = 480, Height = 480 };
                            window.LoadConfig1();
                            window.Content = uc;
                            window.ShowDialog();
                            var nodeDic2 = uc.ToNodeDic();
                            dic.Clear();
                            foreach (var node in nodeDic2)
                            {
                                dic.Add(node.Key, new comm.objst.DItemCategory
                                {
                                    Name = node.Value.Name,
                                    Parent = node.Value.Parent
                                });
                            }
                            Fill();
                        });
                        contextMenu.Items.Add(mEditAll);
                        #endregion
                    }

                    tvi.ContextMenu = contextMenu;
                    #endregion

                    tviDic.Add(key, tvi);
                    treeView.Items.Add(tvi);
                }
                #endregion

                #region sub
                foreach (var key3 in dic.Keys)
                {
                    if (key3.ToString().ToLower().IndexOf(stxt) == -1)
                    {
                        continue;
                    }
                    var item = dic[key3];
                    var dd = (comm.objst.DDefine)item;
                    var hKey = key + "," + key3;
                    var sp = new StackPanel { Orientation = Orientation.Horizontal };

                    #region icon
                    try
                    {
                        var bitmap = new BitmapImage();
                        bitmap.FromFile("icon/" + key.ToLower() + ".png");
                        sp.Children.Add(new Image
                        {
                            Source = bitmap,
                            Width = bitmap.PixelWidth,
                            Height = bitmap.PixelHeight,
                            Margin = new Thickness(0, 0, 4, 0),
                            VerticalAlignment = VerticalAlignment.Center
                        });
                    }
                    catch (Exception)
                    {
                    }
                    #endregion

                    #region tbName
                    var tbName = new TextBlock
                    {
                        Text = key3.ToString() + (dd.Name != "" ? "(" + dd.Name + ")" : ""),
                        MinWidth = 120,
                        Background = new SolidColorBrush(Color2.Transparent()),
                        VerticalAlignment = VerticalAlignment.Center
                    };
                    sp.Children.Add(tbName);
                    #endregion

                    #region tbName2
                    var tbName2 = new TextBox
                    {
                        Tag = hKey,
                        Text = key3.ToString(),
                        MinWidth = 120,
                        Padding = new Thickness(0),
                        BorderBrush = new SolidColorBrush(Color2.Black(10)),
                        VerticalAlignment = VerticalAlignment.Top,
                        Visibility = Visibility.Collapsed
                    };
                    #region event
                    tbName2.KeyDown += new KeyEventHandler((o, e) =>
                    {
                        if (e.Key == Key.Enter)
                        {
                            tbName.Visibility = Visibility.Visible;
                            tbName2.Visibility = Visibility.Collapsed;
                        }
                    });
                    tbName2.LostFocus += new RoutedEventHandler((o, e) =>
                    {
                        tbName.Visibility = Visibility.Visible;
                        tbName2.Visibility = Visibility.Collapsed;
                    });
                    tbName2.IsVisibleChanged += new DependencyPropertyChangedEventHandler((o, e) =>
                    {
                        if (tbName2.Visibility == Visibility.Visible)
                        {
                            comm.ThreadHelper.Run(() =>
                            {
                                Thread.Sleep(100);
                                Dispatcher.BeginInvoke(new Action(() =>
                                {
                                    tbName2.Focus();
                                    tbName2.SelectAll();
                                }));
                            });
                        }
                        else if (tbName2.Visibility == Visibility.Collapsed)
                        {
                            var ss = tbName2.Tag.ToString().Split(',');
                            var newKey = tbName2.Text.Trim();
                            if (ss[1] == newKey)
                            {
                                return;
                            }
                            var idic = _valueDic[ss[0]];
                            if (!idic.Contains(newKey))
                            {
                                var obj = idic[ss[1]];
                                idic.Remove(ss[1]);
                                idic.Add(newKey, obj);
                                Fill();
                            }
                            else
                            {
                                tbName2.Text = ss[1];
                            }
                        }
                    });
                    #endregion
                    sp.Children.Add(tbName2);
                    #endregion

                    //#region DClassBind
                    //if (item is comm.objst.IClassBind)
                    //{
                    //    var cb = (comm.objst.IClassBind)item;
                    //    if (!_mainJS.AllObjEVDic.ContainsKey(hKey))
                    //    {
                    //        _mainJS.AllObjEVDic.Add(hKey, new comm.objst.DObjEV());
                    //    }
                    //    server.app.DataManager.VerifyObjEV(cb.ClassType, comm.lib.ObjEVType.DOBJ, _mainJS.AllObjEVDic[hKey].EVDic);

                    //    tbName.Text = key3.ToString() + " (" + cb.ClassType + ", " + _mainJS.AllObjEVDic[hKey].EVDic.Count + ") ";
                    //}
                    //#endregion

                    var tvi2 = new TreeViewItem
                    {
                        Header = sp,
                        Tag = hKey
                    };
                    #region event
                    tvi2.MouseDoubleClick += new MouseButtonEventHandler((o, e) =>
                    {
                        tbName.Visibility = Visibility.Collapsed;
                        tbName2.Visibility = Visibility.Visible;
                    });
                    tvi2.KeyDown += new KeyEventHandler((o, e) =>
                    {
                        if (e.Key == Key.F2)
                        {
                            tbName.Visibility = Visibility.Collapsed;
                            tbName2.Visibility = Visibility.Visible;
                        }
                    });
                    #endregion
                    if (_mainJS.DesignSelKey == hKey)
                    {
                        tvi2.IsSelected = true;
                    }
                    if (stxt != "")
                    {
                        tviDic[key].IsExpanded = true;

                        #region hightlight
                        var ss = comm.StringHelper.SplitText(tbName.Text, stxt);
                        tbName.Text = "";
                        if (ss[0] != null)
                        {
                            tbName.Inlines.Add(new TextBlock { Text = ss[0] });
                        }
                        if (ss[1] != null)
                        {
                            tbName.Inlines.Add(new TextBlock
                            {
                                FontWeight = FontWeights.Bold,
                                Text = ss[1]
                            });
                        }
                        if (ss[2] != null)
                        {
                            tbName.Inlines.Add(new TextBlock { Text = ss[2] });
                        }
                        #endregion
                    }

                    #region contextMenu
                    var contextMenu = new ContextMenu { FontSize = 14 };
                    contextMenu.Opened += new RoutedEventHandler((o, e) =>
                    {
                        tvi2.IsSelected = true;
                    });
                    TextOptions.SetTextFormattingMode(contextMenu, TextFormattingMode.Display);

                    var mCopy = new MenuItem
                    {
                        Tag = hKey,
                        Header = new TextBlock { Text = "复制" }
                    };
                    mCopy.Click += new RoutedEventHandler(mCopy_Click);
                    contextMenu.Items.Add(mCopy);

                    var mDel = new MenuItem
                    {
                        Tag = hKey,
                        Header = new TextBlock { Text = "删除" }
                    };
                    mDel.Click += new RoutedEventHandler(mDel_Click);
                    contextMenu.Items.Add(mDel);

                    tvi2.ContextMenu = contextMenu;
                    #endregion

                    tviDic[key].Items.Add(tvi2);
                }
                #endregion

                var tb = new TextBlock
                {
                    Text = key,
                    FontSize = 14,
                    Foreground = new SolidColorBrush(Color2.Black(50))
                };
                tb.Inlines.Add(new TextBlock
                {
                    Text = " (" + tviDic[key].Items.Count + ")",
                    FontSize = 12,
                    Foreground = new SolidColorBrush(Color2.Black(50))
                });
                tviDic[key].Header = tb;
                if (tviDic[key].Items.Count == 0)
                {
                    tviDic[key].Visibility = Visibility.Collapsed;
                }
            }
        }

        void SaveFile()
        {
            try
            {
                App.DefineFile.WriteMainJS(_valueDic);
                App.DefineFile.Reload();

                var bytes = comm.BinarySerializer.Serialize(_mainJS);
                io.File.WriteAllBytes(_fileName, bytes);

                MakeSign();
            }
            catch (Exception ex)
            {
                MessageBox.Show("save file:" + _fileName + " err!" + ex.Message);
            }
        }
        void OpenFile()
        {
            _valueDic = App.DefineFile.CloneValueDic();
            App.DefineFile.FilePathTo(_valueDic, comm.objst.URIType.RELATIVE);

            try
            {
                App.DefineFile.Reload();

                _mainJS = comm.BinarySerializer.Deserialize<comm.objst.DMainJS>(io.File.ReadAllBytes(_fileName));

                MakeSign();
                Fill();
            }
            catch (Exception ex)
            {
                MessageBox.Show("open file:" + _fileName + " err!" + ex.Message);
            }
        }
        void MakeSign()
        {
            _sign1 = comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_mainJS));
            _sign2 = comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_valueDic));
        }
        bool CheckSignChange()
        {
            return
                _sign1 != comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_mainJS)) ||
                _sign2 != comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_valueDic));
        }
    }
}